home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / vblock / vblock.txt < prev   
Text File  |  1991-09-01  |  12KB  |  330 lines

  1. ALLOCATING PROTECTED MEMORY IN VISUAL BASIC
  2. by Brent K. Langley  CSID: 70312,2142
  3.  
  4. This document contains some memory pointers (pun intended) for securing 
  5. fixed memory buffer allocations from Visual BASIC.
  6.  
  7. As far as I understand it, you've got your choice of two places
  8. where memory can be allocated: Locally (I guess that this would be
  9. Visual BASIC's own local heap) or globally (all the rest of available
  10. memory).  Window's memory management doesn't give you a physical address
  11. when you allocate memory (using API calls) but rather a "handle" that it 
  12. can cross reference to the correct memory location when it needs to.  When
  13. not needed, it is free to move the block around in your system's memory
  14. space to allow for reorganization of fragmented memory chunks and to 
  15. make larger contiguous memory areas.  Programmers are warned in Windows
  16. that physical memory location pointers are transient and might be changed
  17. if something happens to request a big block of memory.  Some movement of 
  18. memory blocks is just shifts in linear memory space.  Some moves are in
  19. and out of EMS memory banks (if you have EMS memory boards). Some are in and 
  20. out and around in extended memory (on 286 and better machines.)  And some
  21. memory swaps are actually paged to disk (this is why you see your disk light
  22. blink a lot when you have a lot of programs active i.e. in and out of the TEMP
  23. subdirectory area of your disk.)  
  24.  
  25. To get a physical memory address, you have to de-reference the handle to 
  26. find out where the block currently is in memory land.  BUT VB passes you
  27. an address of an already de-referenced block in a DLL call.  As soon as you 
  28. get this address, you can call an API function to get the handle and then ask 
  29. Windows to protect it's location.  There are several ways to do this.
  30.  
  31. Lock will add to a counter, indicating the number of apps that don't want
  32. a memory block to move.  Its unclear from the SDK docs, but Locked doesn't
  33. always seem to mean that its really Locked.
  34.  
  35. Sooooo, you can Wire a memory block.  This makes sure that the block of memory
  36. is below the EMS line (it won't get paged out to EMS memory behind your 
  37. back) and it gets locked.  Wire will move memory if necessary to get your block
  38. below this "EMS line", so your original pointer is no longer valid.
  39.  
  40. Also, with extended memory things can shift around, so there are functions
  41. that do a PageLock for that kind of protection.
  42.  
  43. The SDK docs say that for compatibility, the malloc and calloc functions
  44. will automatically  lock your memory locations for you (but I don't know
  45. what kind of locks)
  46.  
  47. When you no longer need the data to be fixed in memory, you should unlock, 
  48. unwire, unpagelock, ... undo whatever you did to be nice to Windows
  49. memory management system.
  50.  
  51. If anyone else reads this and can provide any deeper enlightenment into
  52. the ways of memory locks and stuff, please hop in!
  53.  
  54. I've included some code that I wrote to lock a couple of ways: completely
  55. in VB, or with DLL routines that allocate locked data for VB to play with.  
  56.  
  57. Although this code calls some routines that I have not uploaded (add_group,
  58. send_datagram, and delete_name) I think they can show you how to use these
  59. routines in your own programs.  Notice that my nballoc returns a long integer
  60. that is really a far pointer to the locked memory space.  Use LSTRCPY to copy
  61. the contents of this allocated buffer to or from a VB string.  Any DLL function
  62. that requires a parameter of type ByVal As String could be changed to As Any. 
  63. (see the bottom of page 385 in the VB Programmer's Guide.)  Then when passing
  64. a string, the routine gets the address of the string.  When passing a value
  65. returned by my alloc routines, send ByVal <Variable> so that the contents 
  66. (i.e. the memory location of the buffer) is passed to the DLL, not the address
  67. of your variable called <Variable>.
  68.  
  69. Of course, you can also do all memory allocation/deallocation from completely
  70. within a DLL using Window's API calls or with malloc and free.  But since 
  71. this was sent mainly to help VB People (VB'ers VBites VBees what are we?) I
  72. won't take up space with purely C programming.
  73.  
  74.  
  75. /*--------------------------------------------------------------------*/
  76. /* NBMEMORY.C to make NBMEMORY.DLL  by  Brent K. Langley  9/1/91      */
  77. /*--------------------------------------------------------------------*/
  78. /*  Code to allocate memory from the global heap and lock it in place */
  79. /*  This code will make a DLL that can be called from Visual BASIC    */
  80. /*  Code was originally made to create network buffers that had to    */
  81. /*  stay in place, waiting for a hardware interrupt to access them.   */
  82. /*  In the meantime, Window's memory management should not try to move*/
  83. /*  them around.  .... Brent K. Langley  CSID: 70312,2142             */
  84. /*--------------------------------------------------------------------*/
  85.  
  86. #include <windows.h>
  87.  
  88. /* Visual BASIC Declaration Format:                                         */
  89. /* Declare Function nballoc Lib "nbmemory.dll" (ByVal size As Long) As Long */
  90.  
  91. char far * far pascal _export nballoc( unsigned long size )
  92.   {
  93.   unsigned mHandle;
  94.   char far * mPtr;
  95.  
  96.   mHandle = GlobalAlloc( GMEM_FIXED | 
  97.                          GMEM_NOT_BANKED | 
  98.                          GMEM_ZEROINIT | 
  99.                          GMEM_NODISCARD, size );
  100.  
  101.   if ( mHandle == 0 ) return 0;      /* couldn't get memory allocated */
  102.  
  103.   mPtr = GlobalWire( mHandle );  
  104.  
  105.   if ( mPtr == 0 )                   /* couldn't "wire" memory block then  */
  106.     mPtr = GlobalLock( mHandle );    /* maybe we can just lock it in place */
  107.  
  108.   GlobalPageLock( mHandle );         /* don't let it get virtually paged   */
  109.   return mPtr;                       /* returns far pointer or 0 if unlocked */
  110.   }
  111.  
  112.  
  113. /*  Visual BASIC Declaration format:                                         */
  114. /*  Declare Function nbfree Lib "nbmemory.dll" (mPtr As Long) As Integer     */
  115.  
  116. int far pascal _export nbfree( char far * mPtr )
  117.   {
  118.   unsigned mHandle;
  119.  
  120.   mHandle = GlobalHandle( (unsigned long) mPtr & 0xFFFF ); /*get handle of ptr*/
  121.  
  122.   GlobalPageUnlock( mHandle );
  123.  
  124.   GlobalUnWire( mHandle );
  125.  
  126.   return ! GlobalFree( mHandle ); /*Return TRUE if free/FALSE if still locked*/
  127.   }
  128.  
  129.  
  130. int FAR PASCAL LibMain( HANDLE hInstance, WORD wDataSeg,
  131.                         WORD cbHeapSize, LPSTR lpCmdLine)
  132. {
  133. return 1 ;
  134. }
  135.  
  136. int FAR PASCAL WEP ( int nParmeter )
  137. {
  138. return 1;
  139. }
  140.  
  141. '------------------------------------------------------------
  142. ' Visual BASIC Global Declarations section 
  143. '------------------------------------------------------------
  144.  
  145. '  Global Memory Flags
  146. Global Const GMEM_FIXED = &H0
  147. Global Const GMEM_MOVEABLE = &H2
  148. Global Const GMEM_NOCOMPACT = &H10
  149. Global Const GMEM_NODISCARD = &H20
  150. Global Const GMEM_ZEROINIT = &H40
  151. Global Const GMEM_MODIFY = &H80
  152. Global Const GMEM_DISCARDABLE = &H100
  153. Global Const GMEM_NOT_BANKED = &H1000
  154. Global Const GMEM_SHARE = &H2000
  155. Global Const GMEM_DDESHARE = &H2000
  156. Global Const GMEM_NOTIFY = &H4000
  157. Global Const GMEM_LOWER = GMEM_NOT_BANKED
  158.  
  159. Global Const GHND = (GMEM_MOVEABLE Or GMEM_ZEROINIT)
  160. Global Const GPTR = (GMEM_FIXED Or GMEM_ZEROINIT)
  161.  
  162. Declare Function GlobalAlloc Lib "Kernel" (ByVal wFlags As Integer, ByVal dwBytes As
  163. Long) As Integer
  164. Declare Function GlobalFree Lib "Kernel" (ByVal hMem As Integer) As Integer
  165.  
  166. Declare Function GlobalHandle Lib "Kernel" (ByVal wMem As Integer) As Long
  167.  
  168. Declare Function GlobalLock Lib "Kernel" (ByVal hMem As Integer) As Long
  169. Declare Function GlobalUnlock Lib "Kernel" (ByVal hMem As Integer) As Integer
  170.  
  171. Declare Function GlobalWire Lib "Kernel" (ByVal hMem As Integer) As Long
  172. Declare Function GlobalUnWire Lib "Kernel" (ByVal hMem As Integer) As Integer
  173.  
  174. Declare Function GlobalPageLock Lib "Kernel" (ByVal wSelector As Integer) As Integer
  175. Declare Function GlobalPageUnlock Lib "Kernel" (ByVal wSelector As Integer) As
  176. Integer
  177.  
  178. Declare Sub GlobalFix Lib "Kernel" (ByVal hMem As Integer)
  179. Declare Function GlobalUnfix Lib "Kernel" (ByVal hMem As Integer) As Integer
  180.  
  181.  
  182. '---------------------------------------------------